﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace OrderGeneratorService
{
   class QuoteServer
   {
      Generator gen = new Generator();
      Order order;
      Socket mdpSocket;
      Socket mdcSocket;
      Socket tcpSocket;
      IPAddress groupAddress;
      IPEndPoint mcastEP;
      IPEndPoint localEP;
      byte[] receiveBuffer = new byte[512];
      String mktPrice;
      int quoteNum;

      public QuoteServer(int num)
      {
         quoteNum = num;
         //IP Multicast address
         groupAddress = IPAddress.Parse("224.5.6.7");
         mcastEP = new IPEndPoint(groupAddress, 30002);
         
      }

      public void StartListener()
      {
         Thread listener = new Thread(StartListener);      
         localEP = new IPEndPoint(IPAddress.Loopback, 20000);
         Console.WriteLine("Market-Data Producer Service Started - (Using MultiCast)");
         Console.WriteLine("Waiting for service input ... ");
         tcpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
         tcpSocket.Bind(localEP);
         tcpSocket.Listen(10);
         mdcSocket = tcpSocket.Accept();
         tcpSocket.Close();
         EndPoint endPoint = new IPEndPoint(IPAddress.Any, 0);
         int bytesReceived = mdcSocket.ReceiveFrom(receiveBuffer, ref endPoint);
         if (bytesReceived > 0)
         {
            mdcSocket.Close();
            Console.WriteLine("new thread for listening started");
            listener.Start();
         }
         IPEndPoint mdpEndPoint = (IPEndPoint)endPoint;
         string ser = Encoding.ASCII.GetString(receiveBuffer, 0, bytesReceived);
         ReturnQuotes(ser);
         
      }

      private void ReturnQuotes(string service)
      {
         byte[] sendBuffer = new byte[512];
         List<Order> qList = new List<Order>();
         mdpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
         for (int i = 0; i < quoteNum; i++)
         {
            order = gen.generateOrder(service);
            qList.Add(order);
            
         }

         //qList.Sort(delegate(Order thisItem, Order otherItem) 
         //{
         //   return thisItem.Price.CompareTo(otherItem.Price);
         //});

         foreach (Order order in qList)
         {
            mktPrice = order.ToString();
            Console.WriteLine(mktPrice);
            string[] ord = order.ToStringArray();
            for (int i = 0; i < ord.Length; i++)
            {
               if(i==ord.Length-1 && order.Equals(qList.Last()))
                  ord[i] = ord[i]+"?";
               sendBuffer = Encoding.ASCII.GetBytes(ord[i]);
               //Set multicast TTL
               mdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 3);
               //Send data to multicast address
               mdpSocket.SendTo(sendBuffer, mcastEP);
            }
         }
        
         mdpSocket.Close();
         Console.WriteLine("Market Data sent to group of consumers");
      }

      // Convert an object to a byte array
      private byte[] ObjectToByteArray(List<Order> obj)
      {
         if (obj == null)
            return null;
         BinaryFormatter bf = new BinaryFormatter();
         MemoryStream ms = new MemoryStream();
         bf.Serialize(ms, obj);
         return ms.ToArray();
      }
       
   }
}
